package org.example.batch.service;

import com.alibaba.fastjson.JSONObject;
import org.example.batch.config.RestTemplateConfig;
import org.example.batch.dao.BatchMainTaskDao;
import org.example.batch.dao.BatchSubTaskDao;
import org.example.batch.dao.InputTableInfoDao;
import org.example.batch.model.BatchMainTaskDto;
import org.example.batch.model.BatchSubTaskDto;
import org.example.batch.pojo.BatchMainTable;
import org.example.batch.pojo.BatchSubTable;
import org.example.batch.util.constant.BatchTerMainStatus;
import org.example.batch.util.constant.BatchTerSubStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 主任务逻辑处理类
 *
 * @author hero生仔
 * @date 2025/7/26
 */
@Service
public class BatchMainTaskService {

    private static final Logger LOGGER = LoggerFactory.getLogger(BatchMainTaskService.class);

    @Autowired
    private BatchSubTaskDao batchSubTaskDao;

    @Autowired
    private BatchMainTaskDao batchMainTaskDao;

    @Autowired
    private RestTemplateConfig restTemplateConfig;

    @Autowired
    private InputTableInfoDao inputTableInfoDao;

    @Autowired
    private TransactionTemplate transactionTemplate;

    /**
     * 输入表单表总数
     */
    private int count;

    /**
     * 可用线程数
     */
    @Value("${ter.threadCount}")
    private int threadCount;


    /**
     * 处理主任务，批量生成子任务
     *
     * @param batchMainTaskDto 主任务
     */
    public void handleMainTask(BatchMainTaskDto batchMainTaskDto) {
        List<BatchSubTable> batchSubTables = batchSubTaskDao.queryBatchSubTableInfoByMainTaskId(batchMainTaskDto.getTaskId());
        // 删掉原来主任务创建的子任务
        batchSubTaskDao.deleteSubTable(batchMainTaskDto.getTaskId());
        // 删掉子任务作为主任务的记录
        List<String> subTableIdList = batchSubTables.stream().map(BatchSubTable::getSubTaskId).collect(Collectors.toList());
        batchSubTaskDao.deleteSubTables(subTableIdList);
        // 根据主任务信息生成子任务
        List<BatchSubTable> batchSubTableList = getBatchSubTables(batchMainTaskDto);
        // 批量存储子任务信息和主任务 一个事务
        saveMainAndSubTable(batchMainTaskDto, batchSubTableList);
        // 组装传输的基本信息，批量请求子任务接口
        for (BatchSubTable subTable : batchSubTableList) {
            BatchSubTaskDto subTaskDto = requestSubTable(subTable);
            LOGGER.info("调用子任务接口信息：{}", subTaskDto);
        }
    }

    /**
     * 批量存储子任务信息和主任务
     *
     * @param batchMainTaskDto  主任务dto
     * @param batchSubTableList 子任务集合
     */
    private void saveMainAndSubTable(BatchMainTaskDto batchMainTaskDto, List<BatchSubTable> batchSubTableList) {
        transactionTemplate.execute(transactionStatus -> {
            BatchMainTable batchMainTable = new BatchMainTable();
            try {
                batchMainTable.setMainTaskId(batchMainTaskDto.getTaskId());
                batchMainTable.setStatus(BatchTerMainStatus.INIT.name());
                batchMainTable.setDwSnshDt(new Date());
                batchMainTable.setStartTime(new Date());
                batchMainTable.setEndTime(new Date());
                batchMainTable.setInputTableTotalCount(count);
                batchMainTable.setIncCount(0);
                batchMainTable.setDecCount(0);
                batchMainTable.setUpdateTime(new Date());
                batchMainTaskDao.batchInsertMainTableInfo(batchMainTable);
                batchSubTaskDao.batchInsertSubTableInfos(batchSubTableList);
                // 异常，回滚事务
//                int i = 1 / 0;
            } catch (Exception e) {
                LOGGER.error("插入主任务信息为：{}，插入子任务信息为：{}，插入异常信息：{}", JSONObject.toJSONString(batchMainTable), JSONObject.toJSONString(batchSubTableList), e.getMessage());
                // 回滚事务
                transactionStatus.setRollbackOnly();
                throw e;
            }
            // 提交事务
            return true;
        });
    }

    /**
     * 获取子任务信息
     *
     * @param batchMainTaskDto 子任务
     * @return 子任务集合
     */
    private List<BatchSubTable> getBatchSubTables(BatchMainTaskDto batchMainTaskDto) {
        List<BatchSubTable> batchSubTableList = new ArrayList<>();
        for (int i = 0; i < threadCount; i++) {
            BatchSubTable batchSubTable = new BatchSubTable();
            batchSubTable.setMainTaskId(batchMainTaskDto.getTaskId());
            batchSubTable.setSubTaskId("sub_taskId_" + i);
            batchSubTable.setStatus(BatchTerSubStatus.INIT.name());
            String inputTableName = "input_info_table_" + i;
            batchSubTable.setInputTableName(inputTableName);
            count = inputTableInfoDao.queryInputInfoCount(appendParams(inputTableName));
            batchSubTable.setInputTableTotalCount(count);
            batchSubTable.setInputTableStart(1);
            batchSubTable.setInputTableEnd(count);

            batchSubTableList.add(batchSubTable);
        }
        return batchSubTableList;
    }

    /**
     * 请求子任务
     *
     * @param batchSubTable 子任务
     * @return 主任务信息
     */
    private BatchSubTaskDto requestSubTable(BatchSubTable batchSubTable) {
        String url = "http://localhost:8088/batchsubtask/putDatas";
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.setContentType(MediaType.APPLICATION_JSON);
        BatchSubTaskDto batchSubTaskDto = new BatchSubTaskDto();
        batchSubTaskDto.setSubTaskId(batchSubTable.getSubTaskId());
        HttpEntity<BatchSubTaskDto> r = new HttpEntity<>(batchSubTaskDto, requestHeaders);
        return restTemplateConfig.restTemplate().postForObject(url, r, batchSubTaskDto.getClass());
    }

    private Map<String, Object> appendParams(String tableName) {
        Map<String, Object> params = new HashMap<>();
        params.put("tableName", tableName);
        return params;
    }
}
